﻿using System;
using System.Collections.Generic;
using System.Linq;
using Skynet.CommonLibrary.ThreadRefreshTime.Extension;
using Skynet.CommonLibrary.ThreadRefreshTime.Interface;
using Skynet.CommonLibrary.ThreadRefreshTime.StrateGy;
using Skynet.CommonLibrary.ThreadRefreshTime.RefreshElement;

namespace Skynet.CommonLibrary.ThreadRefreshTime
{
    /// <summary>
    /// 线程刷新管理
    /// </summary>
    ///<remarks>
    /// 作者：         李志强
    /// 开发时间：  2011-03-28
    /// </remarks>
    public class ThreadRefreshManage:IRefreshTimerManage
    {
        readonly Dictionary<IRefreshTimer, IThreadStrategy> _dicTimer = new Dictionary<IRefreshTimer, IThreadStrategy>();
        FixedTimerElement _fixedElement;
        IThreadStrategy _fixedSerategy;
        private readonly Action<IRefreshTimer, Exception> Failed;
     
        public ThreadRefreshManage()
        {
            RefreshInterval = 60 * 1000;
            //注册错误处理事件,如出现异常 则关闭当前任务,记录日志,并通知外部
            Failed = (IRefreshTimer rt, Exception ex)
                => 
                {
                    RemoveRefreshTimer(rt);
                    //记录错误日志
                    rt.WriteErrorLog(ex);

                    if (RefreshFailed != null)
                        RefreshFailed(rt,ex);
                };
        }

        #region IRefreshTimerManage 成员

        /// <summary>
        /// 获取刷新列表
        /// </summary>
        public IList<IRefreshTimer> TimerList
        {
            get
            {
                return _dicTimer.Keys.ToList();
            }
        }

        /// <summary>
        /// 默认刷新间隔
        /// </summary>
        public int RefreshInterval
        {
            private get;
            set;
        }

        //internal void AddRefreshTimer(Action workAction, int interval, IThreadSerategy serategy)
        //{
        //    //创建一个简单刷新元素
        //    IRefreshTimer refTime = new TimerElement(interval);
        //    //执行时间
        //    refTime.ExecutionTime = DateTime.Now;
        //    //刷新操作
        //    refTime.Refresh = (Action<IRefreshTimer, Exception> failed) => { workAction(); };
        //    //唯一标识
        //    if (string.IsNullOrEmpty(refTime.RefreshID))
        //    {
        //        refTime.RefreshID = GetRefreshID;
        //    }

        //    AddRefreshTimer(refTime, serategy);
        //}

        /// <summary>
        /// 添加刷新元素
        /// </summary>
        /// <param name="refTime">刷新元素</param>
        /// <param name="serategy">刷新方式,如果为NULL,则默认为ThreadTimerSerategy</param>
        public void AddRefreshTimer(IRefreshTimer refTime, IThreadStrategy strategy)
        {
        
            if (strategy == null)
            {
                strategy = new ThreadTimerStrategy();
            }

            //验证
            VerifyRefreshTime(refTime);

            IRefreshTaskTimer rtt = refTime as IRefreshTaskTimer;
            if (rtt != null &&
                rtt.TaskStartTime != DateTime.MinValue)
            {
                //如果设置开始时间,则进入另一个控制器
                AddRefreshFixedTimer(rtt, strategy);
            }
            else
            {
                int interval = refTime.RefreshInterval == 0 ? this.RefreshInterval : refTime.RefreshInterval;
                if (interval == 0)
                {
                    //只执行一次
                    refTime.ExecutiveRefresh(Failed, null);
                    //记录日志
                    refTime.WriteDebugLog();
                    Failed(refTime, new Exception("执行完毕"));
                }
                else
                {
                    strategy.StartWork(() =>
                    {
                        //记录日志
                        refTime.WriteDebugLog();
                        //执行刷新操作
                        refTime.ExecutiveRefresh(Failed, null);
                    },
                    interval);
                }
                this._dicTimer.Add(refTime, strategy);
            }
        }
  
        /// <summary>
        /// 必须是设置过开始时间的元素
        /// </summary>
        /// <param name="refTime"></param>
        /// <param name="serategy"></param>
        private void AddRefreshFixedTimer(IRefreshTaskTimer refTime, IThreadStrategy serategy)
        {
            if (_fixedElement == null)
            {
                //维护一个固定间隔的时间管理器(默认1秒)
                _fixedElement = new FixedTimerElement();
                _fixedSerategy = new ThreadStrategy();
                _fixedSerategy.StartWork(() =>
                {
                    _fixedElement.Refresh(Failed);
                },
             _fixedElement.RefreshInterval == 0 ? this.RefreshInterval : _fixedElement.RefreshInterval);
            }

            if (refTime.RefreshInterval == 0)
            {
                refTime.RefreshInterval = this.RefreshInterval;
            }
            //添加元素
            _fixedElement.AddRefreshTimer(refTime, serategy);
          
            this._dicTimer.Add(refTime, serategy);
        }

        /// <summary>
        /// 移除刷新元素
        /// </summary>
        /// <param name="refTime"></param>
        public void RemoveRefreshTimer(IRefreshTimer refTime)
        {
            if (refTime == null)
                return;
            if (this._dicTimer.Keys.Contains(refTime))
            {
                //释放
                if (_fixedElement != null && refTime is IRefreshTaskTimer)
                {
                    _fixedElement.RemoveRefreshTimer(refTime as IRefreshTaskTimer);
                }
                IThreadStrategy serate = this._dicTimer[refTime];
                this._dicTimer.Remove(refTime);
                if (serate != null)
                {
                    serate.StopWork();
                    //记录日志
                    refTime.WriteInfoLog("结束任务");
                }
            }
        }

        public void RemoveAll()
        {
            if (this._dicTimer.Count > 0)
            {
                foreach (var obj in this._dicTimer.Keys)
                {
                    _fixedElement.RemoveRefreshTimer(obj as IRefreshTaskTimer);
                    IThreadStrategy serate = this._dicTimer[obj];
                
                    if (serate != null)
                    {
                        serate.StopWork();
                        //记录日志
                        obj.WriteInfoLog("结束任务");
                    }
                }
                this._dicTimer.Clear();
            }
        }

        /// <summary>
        /// 异常处理委托
        /// </summary>
        public Action<IRefreshTimer, Exception> RefreshFailed
        {
            set;
            private get;
        }
     
        #endregion

        //获取唯一标识
        private string GetRefreshID
        {
            get { return Guid.NewGuid().ToString(); }
        }

        /// <summary>
        /// 属性验证
        /// </summary>
        /// <param name="reft"></param>
        private void VerifyRefreshTime(IRefreshTimer reft)
        {
            if (reft == null)
                throw new Exception("刷新元素不能为空");
            reft.ExecutionTime = DateTime.Now;
            //唯一标识
            if (string.IsNullOrEmpty(reft.RefreshID))
            {
                reft.RefreshID = GetRefreshID;
            }

            reft.Verify();
        }
    }
}
